<?php

defined('BASEPATH') OR exit('No direct script access allowed');

/*
                            _ooOoo_  
                           o8888888o  
                           88" . "88  
                           (| -_- |)  
                            O\ = /O  
                        ____/`---'\____  
                      .   ' \\| |// `.  
                       / \\||| : |||// \  
                     / _||||| -:- |||||- \  
                       | | \\\ - /// | |  
                     | \_| ''\---/'' | |  
                      \ .-\__ `-` ___/-. /  
                   ___`. .' /--.--\ `. . __  
                ."" '< `.___\_<|>_/___.' >'"".  
               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
                 \ \ `-. \_ __\ /__ _/ .-` / /  
         ======`-.____`-.___\_____/___.-`____.-'======  
                            `=---='  
  
         .............................................  
                  佛祖保佑             永无BUG 
*/

/**
 * Description of My_Controller
 *
 * @author Doufu <442958506@qq.com>
 */
class MY_Controller extends CI_Controller {

	protected $page = array();
	
	const __ID = '__id';

	public function __construct() {
		parent::__construct();
		date_default_timezone_set('Asia/Shanghai');
	}

	public function toSimpleArray($data, $key) {
		$res = array();
		if(!empty($data)) {
			foreach ($data as $v) {
				if(isset($v[$key]))
					$res[] = $v[$key];
			}
		}
		return $res;
	}
	
	public function isPost() {
		return empty($_POST) ? false : true;
	}

	public function post($index = NULL, $default = 0, $xss_clean = NULL) {
		$post = $this->input->post($index, $xss_clean);
		return !empty($post) ? $post : $default;
	}

	public function get($index = NULL, $default = 0, $xss_clean = NULL) {
		$get = $this->input->get($index, $xss_clean);
		return !empty($get) ? $get : $default;
	}

}

/**
 * Description of Backend
 *
 * @author Doufu <442958506@qq.com>
 */
class Backend_Controller extends MY_Controller {

	const ROLE_SUPER_ADMIN = '0';
	const RULE_ADMIN = '1';
	const __ID_PARAM = 'manager';

	public $identity = NULL;

	public function __construct() {
		parent::__construct();
		$PHPSESSID = $this->post('PHPSESSID');
		if(!empty($PHPSESSID) && strlen($PHPSESSID) == 40) {
			session_id($PHPSESSID);
		}
		$this->load->library('session');
		$this->load->library('html_helper');
		$this->identity = $this->session->all_userdata();
		if ($this->isGuest()) {
			if($this->input->is_ajax_request()) {
				$this->renderJson(301);
			}
			$this->session->sess_destroy();
			redirect(site_url('backend/Login/index'));
		}
		$this->page = $this->pagination();
	}

	/**
	 * 后台分页信息
	 * @param number $_pageNum
	 * @param number $_numPerPage
	 * @param string $_field
	 * @param string $_orderBy
	 * @return array
	 */
	protected function pagination($_pageNum=1, $_numPerPage=20, $_field='id', $_orderBy='asc') {
		$pageNum = intval($this->post('pageNum', $_pageNum));
		$numPerPage = intval($this->post('numPerPage', $_numPerPage));
		$orderBy = $this->post('orderDirection', $_orderBy);
		$field = $this->post('orderField', $_field, true);
		
		if($pageNum < 1) {
			$pageNum = $_pageNum;
		}
		if($numPerPage < 1) {
			$numPerPage = $_numPerPage;
		}
		if(!in_array($orderBy, array('asc','desc'))) {
			$orderBy = $_orderBy;
		}
		return array(
			'pageNum' => $pageNum,
			'limit' => $numPerPage,
			'order_by' => $orderBy,
			'field' => $field,
			'offset' => $numPerPage * ($pageNum - 1)
		);
	}
	
	/**
	 * 判断是否是来宾
	 * 
	 * @return boolean
	 */
	protected function isGuest() {
		return (!empty($this->identity) && isset($this->identity[parent::__ID]) && $this->identity[parent::__ID] == self::__ID_PARAM) ? false : true;
	}

	protected function isValidRequest() {
		if (!$this->input->is_ajax_request()) {
			exit('No direct script access allowed');
		}
	}

	/**
	 * Ajax返回
	 * 
	 * @param type $statusCode
	 * @param type $msg
	 * @param type $options
	 */
	protected function renderJson($statusCode, $msg='', $options=array()) {
		$this->lang->load('code');
		$data['statusCode'] = $statusCode;
		if(empty($msg)) {
			$data['message'] = $this->lang->line("e{$statusCode}");
		} else {
			$data['message'] = $msg;
		}
		if(!empty($options)) {
			$data = array_merge($data, $options);
		}
		echo json_encode($data);
		exit();
	}
}

/**
 * Description of REST_Controller
 *
 * @author Doufu <442958506@qq.com>
 */
class REST_Controller extends MY_Controller {

	const STATUS_DELETE = '0';
	const STATUS_PROCESSING = '1';
	const STATUS_ACTIVE = '10';
	
	const ROLE_USER = '0';
	const ROLE_DILIVERIER = '1';
	const ROLE_AGENT = '2';
	
	const PAY_METHOD_ALIPY = '1';
	const PAY_METHOD_WECHAT = '2';
	const PAY_METHOD_CASH = '3';
	
	const PAY_STATUS_CLOSE = '0'; //支付已关闭
	const PAY_STATUS_UNPAY = '1'; //等待支付
	const PAY_STATUS_PAYED = '2'; //已支付、支付宝或微信支付
	const PAY_STATUS_CASH = '3'; //货到付款
	const PAY_STATUS_WAIT_DELIVER = '4'; //等待派送
	const PAY_STATUS_DELIVERING = '5'; //派送中
	const PAY_STATUS_SIGNED = '6'; //已签收
	const PAY_STATUS_FINISH = '7'; //已完成
	const PAY_STATUS_REFUNDING = '8'; //退款申请中
	const PAY_STATUS_REFUNDED = '9'; //已退款
	const PAY_STATUS_COMPLAIN = '10'; //投送
	
	const __ID_PARAM = 'users';
	
	protected $identity = NULL;

	public function __construct() {
		parent::__construct();
		header('Access-Control-Allow-Origin: *');
		header('Content-Type:application/json;charset=UTF-8');
		$this->lang->load('code');
		$this->config->load('rest');

		if (!$this->authorization()) {
			$this->renderJson(11202);
		}
		$this->page = $this->pagination();
	}

	/**
	 * 接口分页信息
	 * @param number $_pageNum
	 * @param number $_numPerPage
	 * @param string $_field
	 * @param string $_orderBy
	 * @return array
	 */
	protected function pagination($_offset=0, $_numPerPage=5, $_field='id', $_orderBy='asc') {
		$offset = intval($this->post('offset', $_offset));
		$numPerPage = intval($this->post('numPerPage', $_numPerPage));
		$orderBy = $this->post('orderDirection', $_orderBy);
		$field = $this->post('orderField', $_field, true);
		
		if($offset < 0) {
			$offset = $_offset;
		}
		if($numPerPage < 1) {
			$numPerPage = $_numPerPage;
		}
		if(!in_array($orderBy, array('asc','desc'))) {
			$orderBy = $_orderBy;
		}
		return array(
			'offset' => $offset,
			'limit' => $numPerPage,
			'order_by' => $orderBy,
			'field' => $field,
		);
	}
	/*	 * ************************************************************
	 *
	 * 	使用特定function对数组中所有元素做处理
	 * 	@param	string	&$array		要处理的字符串
	 * 	@param	string	$function	要执行的函数
	 * 	@return boolean	$apply_to_keys_also		是否也应用到key上
	 * 	@access public
	 *
	 * *********************************************************** */

	private function arrayRecursive(&$array, $function, $apply_to_keys_also = false) {
		static $recursive_counter = 0;
		if (++$recursive_counter > 1000) {
			die('possible deep recursion attack');
		}
		foreach ($array as $key => $value) {
			if (is_array($value)) {
				$this->arrayRecursive($array[$key], $function, $apply_to_keys_also);
			} else {
				$value = str_replace('"', ' ', $value);
				$value = str_replace("\t", ' ', $value);
				$value = str_replace('\\', '\\\\', $value);
				$value = str_replace('\\\\n', '\\n', $value);
				$value = str_replace("\r\n", '', $value);
				$array[$key] = $function($value);
			}

			if ($apply_to_keys_also && is_string($key)) {
				$new_key = $function($key);
				if ($new_key != $key) {
					$array[$new_key] = $array[$key];
					unset($array[$key]);
				}
			}
		}
		$recursive_counter--;
	}

	/*	 * ************************************************************
	 *
	 * 	将数组转换为JSON字符串（兼容中文）
	 * 	@param	array	$array		要转换的数组
	 * 	@return string		转换得到的json字符串
	 * 	@access public
	 *
	 * *********************************************************** */

	private function json_iencode($array) {
		$this->arrayRecursive($array, 'urlencode', true);
		$json = json_encode($array);
		$str = urldecode($json);
		$str = str_replace(array("\t", "\r\n", "\n\r", "\r", "\n"), '', $str);
		return $str;
	}
	
	protected function renderJson($resultCode, $data = array()) {

		$data['resultCode'] = $resultCode;
		if(!isset($data['msg'])) {
			$data['msg'] = $this->lang->line("e$resultCode");
		}
		$data['timestamp'] = time();

		$signData = $this->toArray($data);
		asort($signData);
		$signString = '';
		foreach ($signData as $value) {
			if (is_string($value)) {
				$signString .= $value;
			}
		}
		$signString .= config_item('user.appSecret');
		$data['sign'] = md5($signString);

		$callback = $this->post('callback');
		$response = $this->json_iencode($data);
		if (empty($callback)) {
			echo $response;
		} else {
			echo "{$callback}({$response})";
		}
		exit();
	}

	protected function toArray($array, $data = array()) {
		if (!empty($array)) {
			foreach ($array as $k => $v) {
				if (is_array($v)) {
					$data = $this->toArray($v, $data);
				} elseif ($v != '' && !in_array($k, array('_', 'callback', 'sign'), true)) {
					$data[] = $v;
				}
			}
		}
		return $data;
	}

	protected function authorization() {
		$requestArray = $this->input->post();
		if (isset($requestArray['timestamp']) && isset($requestArray['sign']) && !empty($requestArray['sign'])) {
			$timeout = config_item('user.requestTimeout');
			if (time() - $requestArray['timestamp'] > $timeout) {
				return false;
			}
			$linearArray = $this->toArray($requestArray);
			if (isset($_FILES) && !empty($_FILES)) {
				foreach ($_FILES as $file) {
					$linearArray[] = md5_file($file['tmp_name']);
				}
			}
			asort($linearArray, SORT_STRING);
			$signString = '';
			foreach ($linearArray as $value) {
				if ($value != '' && is_string($value)) {
					$signString .= $value;
				}
			}
			$signString .= config_item('user.appSecret');
			if (md5($signString) == strtolower($requestArray['sign'])) {
				return true;
			}
		}
		return false;
	}

	protected function authenticate() {
		$accessToken = $this->post(config_item('user.tokenParam'));
		if (is_string($accessToken) && substr_count($accessToken, '.') > 0) {
			$keys = explode('.', $accessToken);
			$tokenExpireTime = config_item('user.tokenExpireTime');
			if ($tokenExpireTime > 0 && (time() > end($keys) + $tokenExpireTime)) {
				return NULL;
			} else {
				session_id($keys[0]);
				$this->load->library('session');
				$identity = $this->session->all_userdata();
				$resecure = $this->resecure($identity, $keys[0]);
				$this->identity = (isset($resecure['updated_at']) 
						&& $resecure['updated_at'] == end($keys)) ? $resecure : NULL;
				return $this->identity;
			}
		}
		return NULL;
	}
	//信春哥得永生
	protected function resecure($identity, $token) {
		if (empty($identity)) {
			if(config_item('user.resecure')) {
				$this->load->model('api/User_model', 'users');
				$row = $this->users->get_row(array('access_token' => $token, 'status'=>self::STATUS_ACTIVE));
				if (!empty($row)) {
					$SESS = array(
							'uid' => $row['id'],
							'username' => $row['username'],
							'role' => $row['role'],
							'updated_at' => $row['updated_at'],
							'status' => $row['status'],
							parent::__ID => self::__ID_PARAM,
					);
					$this->session->set_userdata($SESS);
					session_write_close();
					return $SESS;
				}		
			}
			$this->session->sess_destroy();	
		}
		return $identity;
	}
	//判断是否已注册session且为用户
	protected function isGuest() {
		$this->authenticate();
		return !empty($this->identity) && ($this->identity['status'] == self::STATUS_ACTIVE)
		&& isset($this->identity[parent::__ID]) && ($this->identity[parent::__ID] == self::__ID_PARAM) ? false : true;
	}

}

class REST_Member_Controller extends REST_Controller {
	
	public function __construct() {
		parent::__construct();
		if ($this->isGuest()) {
			$this->renderJson(10002);
		}
	}
}
class REST_D_Controller extends REST_Controller {
	
	const __ID_PARAM = 'diliveriers';
	
	//信春哥得永生
	protected function resecure($identity, $token) {
		if (empty($identity)) {
			if(config_item('user.resecure')) {
				$this->load->model('api/Agent_model', 'Agent');
				$row = $this->Agent->get_row(array('access_token' => $token));
				if (!empty($row)) {
					$addressIds = $this->Agent->getAddressId($row['id']);
					$SESS = array(
							'uid' => $row['id'],
							'nickname' => $row['nickname'],
							'username' => $row['username'],
							'address_id' => $addressIds,
							'role' => $row['role'],
							'status' => $row['status'],
							'updated_at' => $row['updated_at'],
							parent::__ID => self::__ID_PARAM,
					);
					$this->session->set_userdata($SESS);
					session_write_close();
					return $SESS;
				}		
			}
			$this->session->sess_destroy();
		}
		return $identity;
	}
	//判断是否已注册session且为小哥
	protected function isGuest() {
		$this->authenticate();
		return !empty($this->identity) && isset($this->identity[parent::__ID]) && ($this->identity[parent::__ID] == self::__ID_PARAM) ? false : true;
	}
}
class REST_Diliveriers_Controller extends REST_D_Controller {
			
	public function __construct() {
		parent::__construct();
		if (!$this->isDiliverier()) {
			$this->renderJson(10002);
		}
	}
	//判断是否是小哥
	protected function isDiliverier() {
		return !$this->isGuest() && ($this->identity['status'] == parent::STATUS_ACTIVE)
				&& ($this->identity['role'] == self::ROLE_DILIVERIER || $this->identity['role'] == self::ROLE_AGENT);
	}
	//判断是否是网点管理员
	protected function isProvider() {
		return !$this->isGuest() && ($this->identity['status'] == parent::STATUS_ACTIVE)
				&& $this->identity['role'] == self::ROLE_AGENT;
	}
}